﻿using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;

namespace Normalify
{
	internal class DataTable : IDataTable, IDataReader, IDataRowAdder
	{
		private readonly List<string> _names = new List<string>();
		private readonly List<Type> _dataTypes = new List<Type>();
		private readonly List<IDataColumn> _columns = new List<IDataColumn>();
		private readonly Dictionary<Guid, int> _maps = new Dictionary<Guid, int>();
		private readonly List<DqDataRow> _rows = new List<DqDataRow>();
		private readonly List<object[]> _data = new List<object[]>();

		public DataTable(IEnumerable<IDataColumn> columns, IEnumerable<string> names, IEnumerable<Type> types)
		{
			_columns = columns.ToList();
			_dataTypes = types.ToList();
			_names = names.ToList();
			Contract.Assert(_columns.Count == _dataTypes.Count && _dataTypes.Count == _names.Count());
			_maps = _columns.Select((c, i) => new {C = c, I = i}).ToDictionary(kvp => kvp.C.Id, kvp => kvp.I);
			foreach (var col in _columns.OfType<IOwnedByTable>())
			{
				col.SetOwner(this);
			}
		}

		public IEnumerable<IDataColumn> Columns { get { return _columns; } }

		public string GetName(IDataColumn column)
		{
			var idx = _maps[column.Id];
			return _names[idx];
		}

		public IDataColumn GetColumn(string name)
		{
			var idx = _names.IndexOf(name);
			return _columns[idx];
		}

		public Type GetDataType(IDataColumn column)
		{
			var idx = _maps[column.Id];
			return _dataTypes[idx];
		}

		public IEnumerable<IDataRow> Rows { get { return _rows; } }

		public void AddRow(params object[] row)
		{
			_data.Add(row);
			_rows.Add( new DqDataRow(this, _data.Count - 1));
		}

		public object Read(IDataRow row, IDataColumn col)
		{
			var colIdx = _maps[col.Id];
			return _data[row.Id][colIdx];
		}
	}
}